#ifndef __pthread_hpp__
#define __pthread_hpp__

// 模拟c++，封装linux原生线程库pthread，封装线程

#include <pthread.h>
#include <string>
#include <unistd.h>
#include <functional>
using namespace std;

namespace mypthread
{
    // 模板
    template <typename T>
    using func_t = function<void(T&)>; // 定义了一个函数类型，using等价于typedef

    template <class T>
    class Thread
    {
    public:
        Thread(func_t<T> func, T& data, string name) : _func(func), _data(data), _name(name) // func是线程要执行的方法，data是参数
        {
            pthread_create(&_tid, nullptr, pthreadRoutine, this);
            //这里调用pthread_create方法的注意事项
            //1、pthread_create要执行的新方法返回值是void*，参数类型void*，如果自己定义的函数类型不符，那么需要给函数套一层，使参数符合，如pthreadRoutine
            //2、套完后的函数pthreadRoutine必须是静态成员函数，因为非静态成员函数有个隐藏的参数是this指针
            //3、要想在静态成员函数pthreadRoutine中调用非静态成员，只能让它的参数是this指针，所以pthread_create参数中最后一个是this指针
        }
        
        static void* pthreadRoutine(void* p) // 非静态成员函数，会有一个隐藏的参数，不符合线程调用的参数类型
        {
            //Thread<T>* self = (Thread<T>*)p;
            Thread<T>* self = static_cast<Thread<T>*>(p);
            self->_func(self->_data); //静态成员函数只能调用静态成员变量和函数，因为没有this指针,除非传参有this    
            return nullptr;
        }
        
        void join()
        {
            pthread_join(_tid, nullptr);
        }

        void detach()
        {
            pthread_detach(_tid);
        }

        const char* getName()
        {
            return _name.c_str();
        }

    private:
        pthread_t _tid; // 线程的tid
        string _name;   // 线程的名字
        func_t<T> _func;  // 线程要执行的方法
        T& _data; //方法的参数，引用是为了让所有线程看到同一份数据
    };

}

#endif

